/*
 * *
 *  * Created with IntelliJ RustRover.
 *  * Description:
 *  * Copyright Author: ZhenYi
 *  * DateTime: 2024/2/15 下午10:40
 *
 */

use regex::Regex;
use rustis::commands::ConnectionCommands;
use rustis::resp::cmd;
use salvo::http::headers::Authorization;
use salvo::http::headers::authorization::Basic;
use uuid::Uuid;
use crate::utensil::basic_auth::{BasicAuthOps, BasicAuthQueue};

#[allow(unused)]
#[derive(Clone)]
pub struct LocalBasicAuth{
    redis:rustis::client::Client,
    rx:tokio::sync::mpsc::Sender<BasicAuthQueue>
}

impl LocalBasicAuth {
    #[allow(unused)]
    pub fn new(redis:rustis::client::Client,rx:tokio::sync::mpsc::Sender<BasicAuthQueue>) -> LocalBasicAuth {
        LocalBasicAuth {
            redis,
            rx
        }
    }
    #[allow(unused)]
    pub async fn generate_save_auth_basic_admin(&self) -> Authorization<Basic> {
        let username = Uuid::new_v4().to_string();
        let password = Uuid::new_v4().to_string();
        let auth = Authorization::basic(username.clone().as_str(),password.clone().as_str());
        self.rx.send(
            BasicAuthQueue::new(
                BasicAuthOps::AddBasic,
                (username,format!("{}+admin",password))
            )
        ).await.unwrap();
        return auth
    }
    #[allow(unused)]
    pub async fn generate_save_auth_basic_author(&self) -> Authorization<Basic> {
        let username = Uuid::new_v4().to_string();
        let password = Uuid::new_v4().to_string();
        let auth = Authorization::basic(username.clone().as_str(),password.clone().as_str());
        self.rx.send(
            BasicAuthQueue::new(
                BasicAuthOps::AddBasic,
                (username,format!("{}+author",password))
            )
        ).await.unwrap();
        return auth
    }
    #[allow(unused)]
    pub async fn generate_save_auth_basic_expert(&self) -> Authorization<Basic> {
        let username = Uuid::new_v4().to_string();
        let password = Uuid::new_v4().to_string();
        let auth = Authorization::basic(username.clone().as_str(),password.clone().as_str());
        self.rx.send(
            BasicAuthQueue::new(
                BasicAuthOps::AddBasic,
                (username,format!("{}+expert",password))
            )
        ).await.unwrap();
        return auth
    }
    pub async fn validate_auth_basic_admin(&self,username:&str,password:&str) ->bool{
        self.redis.select(5).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(username),None).await.unwrap();
        if res_body.is_empty(){
            return false
        }
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let body = body.split("+").collect::<Vec<&str>>();
        if body[1] == "admin" {
            if body[0] == password {
                self.rx.send(
                    BasicAuthQueue::new(
                        BasicAuthOps::UpdateBasic,
                        (username.to_string(),"".to_string())
                    )
                ).await.unwrap();
                return true
            }
        }
        false
    }
    pub async fn validate_auth_basic_author(&self,username:&str,password:&str) ->bool{
        self.redis.select(5).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(username),None).await.unwrap();
        if res_body.is_empty(){
            return false
        }

        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let body = body.split("+").collect::<Vec<&str>>();
        if body[1] == "author" {
            if body[0] == password {
                self.rx.send(
                    BasicAuthQueue::new(
                        BasicAuthOps::UpdateBasic,
                        (username.to_string(),"".to_string())
                    )
                ).await.unwrap();
                return true
            }
        }
        false
    }
    pub async fn validate_auth_basic_expert(&self,username:&str,password:&str) ->bool{
        self.redis.select(5).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(username),None).await.unwrap();
        if res_body.is_empty(){
            return false
        }
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let body = body.split("+").collect::<Vec<&str>>();
        if body[1] == "expert" {
            if body[0] == password {
                self.rx.send(
                    BasicAuthQueue::new(
                        BasicAuthOps::UpdateBasic,
                        (username.to_string(),"".to_string())
                    )
                ).await.unwrap();
                return true
            }
        }
        false
    }
}